package org.dtrd.modules.quartz.job;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.func.Func;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.dtrd.common.util.DateUtils;
import org.dtrd.common.util.StringUtil;
import org.dtrd.config.system.Constant;
import org.dtrd.config.system.Constant.RecordState;
import org.dtrd.config.system.Constant.SleepStatus;
import org.dtrd.modules.achievement.entity.bean.SignInAction;
import org.dtrd.modules.achievement.entity.po.DtrdEntRdSigninRecord;
import org.dtrd.modules.achievement.service.impl.DtrdEntRdSigninRecordServiceImpl;
import org.dtrd.modules.record.entity.bean.ValueUplowBean;
import org.dtrd.modules.record.entity.po.*;
import org.dtrd.modules.record.service.*;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * @author xiao
 * @date 2022/8/11 6:11 PM
 */
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Slf4j
public class InitSigninRecordJob implements Job {

    @Autowired
    private ISugarRecordService sugarRecordService;
    @Autowired
    private IBloodPressureRecordService bloodPressureRecordService;
    @Autowired
    private ISportRecordService sportRecordService;
    @Autowired
    private IMedicalRecordService medicalRecordService;
    @Autowired
    private IFoodRecordService foodRecordService;
    @Autowired
    private IHeightWeightRecordService heightWeightRecordService;
    @Autowired
    private IWaistlineRecordService waistlineRecordService;
    @Autowired
    private IKetoneRecordService ketoneRecordService;
    @Autowired
    private IInsulinRecordService insulinRecordService;
    @Autowired
    private ISleepRecordService sleepRecordService;
    @Autowired
    private INutrientRecordService nutrientRecordService;

    /**
     * 打卡记录
     */
    @Autowired
    DtrdEntRdSigninRecordServiceImpl signinRecordService;
    @Autowired
    private IDtrdEntRdUplowRecordService uplowRecordService;


    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        List<DtrdEntRdSigninRecord> recordList = signinRecordService.getAllSigninRecords();
        if (CollectionUtil.isNotEmpty(recordList)) {
            recordList.stream().filter(record -> StrUtil.isNotBlank(record.getSighInJson())).forEach(record -> {
                List<SignInAction> actionList = JSONObject.parseArray(record.getSighInJson(), SignInAction.class);
                actionList.stream()
                        // 过滤有数据的记录
                        .filter(po -> Optional.ofNullable(po.getDataId()).orElse(0) > 0)
                        .forEach(po -> {
                            Constant.RecordType recordType = Constant.RecordType.valueOf(po.getRecordType());
                            if (recordType != null) {
                                switch (recordType) {
                                    case SUGAR: {
                                        handleSigninRecord(sugarRecordService, po, sugar -> {
                                            po.setRecordValue(wrappValue(sugar.getSugarValueSugarValue()));
                                            po.setRecordPhoto(sugar.getRecordPhoto());
                                            po.setRecordTime(wrappRecordTime(sugar.getRecordTime()));
                                        });
                                    }
                                    break;
                                    case BLOOD_PRESSURE:
                                        log.info("InitSigninRecordJob.execute.[context] before consumer po=" + po);
                                        handleSigninRecord(bloodPressureRecordService, po, entity -> {
                                            po.setRecordValue(wrappValue(entity.getBloodPressureHighPressure()));
                                            po.setRecordValue3(wrappValue(entity.getBloodPressureHeartRate()));
                                            po.setRecordValue2(wrappValue(entity.getBloodPressureLowVoltage()));
                                            po.setRecordPhoto(entity.getRecordPhoto());
                                            po.setRecordTime(wrappRecordTime(entity.getRecordTime()));
                                        });
                                        log.info("InitSigninRecordJob.execute.[context] after consumer po=" + po);
                                        break;
                                    case SPORT:
                                        handleSigninRecord(sportRecordService, po, entity -> {
                                            po.setRecordValue(wrappValue(entity.getSportRecordStep()));
                                            po.setRecordDesc(entity.getSportRecordPowerDescribe());
                                            po.setRecordPhoto(entity.getRecordPhoto());
                                            po.setRecordTime(wrappRecordTime(entity.getRecordTime()));
                                        });
                                        break;
                                    case MEDICAL:
                                        handleSigninRecord(medicalRecordService, po, entity -> {
                                            po.setRecordValue(wrappValue(entity.getMedicalRecordStatus()));
                                            po.setRecordDesc(entity.getMedicalRecordDescribe());
                                            po.setRecordPhoto(entity.getMedicalRecordPhoto());
                                            po.setRecordTime(wrappRecordTime(entity.getRecordTime()));
                                        });
                                        break;
                                    case DIET:
                                        handleSigninRecord(foodRecordService, po, entity -> {
                                            po.setRecordPhoto(entity.getRecordPhoto());
                                            po.setRecordTime(wrappRecordTime(entity.getRecordTime()));
                                        });
                                        break;
                                    case WEIGHT:
                                        handleSigninRecord(heightWeightRecordService, po, entity -> {
                                            po.setRecordValue(wrappValue(entity.getHeightWeightWeight()));
                                            po.setRecordValue2(wrappValue(entity.getHeightWeightHeight()));
                                            po.setRecordValue3(wrappValue(entity.getHeightWeightBmi()));
                                            po.setRecordPhoto(entity.getRecordPhoto());
                                            po.setRecordTime(wrappRecordTime(entity.getRecordTime()));
                                        });
                                        break;
                                    case WAIST:
                                        handleSigninRecord(waistlineRecordService, po, entity -> {
                                            po.setRecordValue(wrappValue(entity.getWaistlineValue()));
                                            po.setRecordPhoto(entity.getRecordPhoto());
                                            po.setRecordTime(wrappRecordTime(entity.getRecordTime()));
                                        });
                                        break;
                                    case KETONE:
                                        handleSigninRecord(ketoneRecordService, po, entity -> {
                                            po.setRecordValue(wrappValue(entity.getKetoneValue()));
                                            po.setRecordDesc(entity.getKetoneDescribe());
                                            po.setRecordPhoto(entity.getRecordPhoto());
                                            po.setRecordTime(wrappRecordTime(entity.getRecordTime()));
                                        });
                                        break;
                                    case INSULIN:
                                        handleSigninRecord(insulinRecordService, po, entity -> {
                                            po.setRecordValue(wrappValue(entity.getInsulinInjection()));
                                            po.setRecordDesc(entity.getInsulinDescribe());
                                            po.setRecordPhoto(entity.getRecordPhoto());
                                            po.setRecordTime(wrappRecordTime(entity.getRecordTime()));
                                        });
                                        break;
                                    case SLEEP:
                                        handleSigninRecord(sleepRecordService, po, entity -> {
                                            po.setRecordValue(wrappValue(entity.getSleepStatus()));
                                            po.setRecordPhoto(entity.getRecordPhoto());
                                            po.setRecordTime(wrappRecordTime(entity.getRecordTime()));
                                        });
                                        break;
                                    case NUTRIENT:
                                        handleSigninRecord(nutrientRecordService, po, entity -> {
                                            po.setRecordDesc(entity.getNutrientRecordDescribe());
                                            po.setRecordPhoto(entity.getNutrientRecordPhoto());
                                            po.setRecordTime(wrappRecordTime(entity.getRecordTime()));
                                        });
                                        break;
                                    default:
                                        break;
                                }
                            }
                        });
                record.setSighInJson(JSON.toJSONString(actionList));
            });
            signinRecordService.updateBatchById(recordList,500);
        }
    }

    private String wrappValue(Object value) {
        return Optional.ofNullable(value).map(String::valueOf).orElse(null);
    }

    private String wrappRecordTime(Date recordTIme) {
        return Optional.ofNullable(recordTIme).map(time -> DateUtils.formatDate(time, DateUtils.datetimeFormat.get().toPattern())).orElse(null);
    }

    private <T> void handleSigninRecord(IRecordService<T> recordService,
                                        SignInAction po, Consumer<T> mapper) {
        T entity = wrapper(po.getDataId(), recordService);
        if (entity == null) {
            po.setDataId(0);
            po.setRecordTime(null);
            po.setRecordValue(null);
            po.setRecordValue2(null);
            po.setRecordValue3(null);
            po.setRecordDesc(null);
            po.setRecordPhoto(null);
        } else {
            mapper.accept(entity);
        }
    }

    private <T> T wrapper(Integer dataId, IRecordService<T> recordService) {
        return Optional.ofNullable(dataId).map(recordService::getById).orElse(null);
    }
}
